#include "vector.h"
#include <stdlib.h>
#include <stdio.h>
#include "utest.h"

UTEST(vector, pushpop) {
  ctl_vec_int* vec = ctl_vec_int_new(3).value;
  for (size_t idx = 0; idx < 3; idx++) {
    ctl_vec_int_set_at(vec, idx, (int)idx);
  }
  ctl_vec_int_push_front(vec, -1);
  ASSERT_EQ(ctl_vec_int_size(vec), 4U);
  ASSERT_EQ(ctl_vec_int_get_at(vec, 0).value, -1);
  
  ASSERT_EQ(ctl_vec_int_get_at(vec, 1).value, 0);
  ASSERT_EQ(ctl_vec_int_get_at(vec, 2).value, 1);
  
  ASSERT_EQ(ctl_vec_int_pop_front(vec).value, -1);
  ASSERT_EQ(ctl_vec_int_size(vec), 3U);
  
  ctl_vec_int_push_front(vec, 100);
  ASSERT_EQ(ctl_vec_int_get_at(vec, 0).value, 100); 
  
  ASSERT_EQ(ctl_vec_int_pop_front(vec).value, 100);
  ASSERT_EQ(ctl_vec_int_size(vec), 3U);
  
  ASSERT_EQ(ctl_vec_int_pop_front(vec).value, 0);
  ASSERT_EQ(ctl_vec_int_size(vec), 2U);
  
  ctl_vec_int_push_back(vec, 10);
  ASSERT_EQ(ctl_vec_int_size(vec), 3U);

  ASSERT_EQ(ctl_vec_int_get_at(vec, ctl_vec_int_size(vec) - 1).value, 10);
  ctl_vec_int_push_front(vec, 20);
  ASSERT_EQ(ctl_vec_int_size(vec), 4U);
  
  ASSERT_EQ(ctl_vec_int_get_at(vec, 0).value, 20);
  ctl_vec_int_push_front(vec, 30);
  ASSERT_EQ(ctl_vec_int_size(vec), 5U);

  ASSERT_EQ(ctl_vec_int_get_at(vec, 0).value, 30);
  
  ASSERT_EQ(ctl_vec_int_get_at(vec, 1).value, 20);
  ctl_vec_int_push_back(vec, 50);
  ASSERT_EQ(ctl_vec_int_get_at(vec, ctl_vec_int_size(vec) - 1).value, 50);
  ctl_vec_int_free(vec);
}

UTEST(vector, insert) {
  ctl_vec_int* vec = ctl_vec_int_new(5).value;
  for (size_t idx = 0; idx < 5; idx++) {
    ctl_vec_int_set_at(vec, idx, (int)idx);
  }
  int data_arr[3] = {10, 20, 30};
  ctl_vec_int_insert_range(vec, 3, 3, data_arr);
  ASSERT_EQ(ctl_vec_int_size(vec), 8U);
  int expect_data[8] = {0, 1, 2, 10, 20, 30, 3, 4};
  for (size_t idx = 0; idx < 8; idx++) {
    ASSERT_EQ(ctl_vec_int_get_at(vec, idx).value, expect_data[idx]);
  }
  ctl_vec_int_free(vec);
}

UTEST(vector, insert2) {
  ctl_vec_int* vec = ctl_vec_int_new(5).value;
  for (size_t idx = 0; idx < 5; idx++) {
    ctl_vec_int_set_at(vec, idx, (int)idx);
  }
  int data_arr[3] = {10, 20, 30};
  ctl_vec_int_reserve(vec, 20U);
  ctl_vec_int_insert_range(vec, 3, 3, data_arr);
  ASSERT_EQ(ctl_vec_int_size(vec), 8U);
  int expect_data[8] = {0, 1, 2, 10, 20, 30, 3, 4};
  for (size_t idx = 0; idx < 8; idx++) {
    ASSERT_EQ(ctl_vec_int_get_at(vec, idx).value, expect_data[idx]);
  }
  ctl_vec_int_free(vec);
}

UTEST(vector, remove) {
  ctl_vec_int* vec = ctl_vec_int_new(6).value;
  for (size_t idx = 0; idx < 6; idx++) {
    ctl_vec_int_set_at(vec, idx, (int)idx);
  }
  ctl_vec_int_remove_range(vec, 2, 3);
  ASSERT_EQ(ctl_vec_int_size(vec), 3U);
  int expect_data[3] = {0, 1, 5};
  for (size_t idx = 0; idx < 3; idx++) {
    ASSERT_EQ(ctl_vec_int_get_at(vec, idx).value, expect_data[idx]);
  }
  ctl_vec_int_remove_at(vec, 1);
  int expect_data2[2] = {0, 5};
  for (size_t idx = 0; idx < 2; idx++) {
    ASSERT_EQ(ctl_vec_int_get_at(vec, idx).value, expect_data2[idx]);
  }
  ctl_vec_int_free(vec);
}

UTEST(vector, trim) {
  ctl_vec_int* vec = ctl_vec_int_new(5).value;
  for (size_t idx = 0; idx < 5; idx++) {
    ctl_vec_int_set_at(vec, idx, (int)idx);
  }
  ctl_vec_int_pop_front(vec);
  ctl_vec_int_pop_front(vec);
  ctl_vec_int_pop_front(vec);
  int expect_data[2] = {3, 4};
  for (size_t idx = 0; idx < 2; idx++) {
    ASSERT_EQ(ctl_vec_int_get_at(vec, idx).value, expect_data[idx]);
  }
  ctl_vec_int_free(vec);
}

UTEST(vector, grow) {
  ctl_vec_int* vec = ctl_vec_int_new(1).value;
  for (size_t idx = 0; idx < 1; idx++) {
    ctl_vec_int_set_at(vec, idx, (int)idx);
  }
  ctl_vec_int_push_back(vec, 10);
  ctl_vec_int_push_back(vec, 20);
  ctl_vec_int_push_back(vec, 30);
  ctl_vec_int_push_back(vec, 40);
  int expect_data[6] = {0, 10, 20, 30, 40};
  for (size_t idx = 0; idx < 5; idx++) {
    ASSERT_EQ(ctl_vec_int_get_at(vec, idx).value, expect_data[idx]);
  }

  ctl_vec_int_pop_back(vec);
  ctl_vec_int_pop_back(vec);
  int expect_data2[3] = {0, 10, 20};
  ASSERT_EQ(ctl_vec_int_size(vec), 3U);
  for (size_t idx = 0; idx < 3; idx++) {
    ASSERT_EQ(ctl_vec_int_get_at(vec, idx).value, expect_data2[idx]);
  }
  ctl_vec_int_free(vec);
}

UTEST(vector, copy) {
  ctl_vec_int* vec = ctl_vec_int_new(10).value;
  for (size_t idx = 0; idx < 10; idx++) {
    ctl_vec_int_set_at(vec, idx, (int)idx);
  }
  ctl_vec_int* vec2 = ctl_vec_int_new(1).value;
  ctl_vec_int_copy(vec2, vec);
  int expect_data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  for (size_t idx = 0; idx < 10; idx++) {
    ASSERT_EQ(ctl_vec_int_get_at(vec, idx).value, expect_data[idx]);
  }
  ctl_vec_int_free(vec2);
  ctl_vec_int_free(vec);
}

UTEST(vector, resize) {
  ctl_vec_int* vec = ctl_vec_int_new(1).value;
  ctl_vec_int_resize(vec, 10);
  for (size_t idx = 0; idx < 10; idx++) {
    ctl_vec_int_set_at(vec, idx, (int)idx);
  }
  int expect_data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
  for (size_t idx = 0; idx < 10; idx++) {
    ASSERT_EQ(ctl_vec_int_get_at(vec, idx).value, expect_data[idx]);
  }
  ctl_vec_int_free(vec);
}
UTEST_MAIN()